<template>
    <BaseExercise title="发音练习">
        <template #question>
            <SimpleWord
                class="mb-8 transition"
                :class="
                    exercise.resultCorrect != undefined
                        ? ''
                        : 'blur select-none'
                "
                :word="exercise.word"
            />

            <PhoneticSymbol
                class="mb-8 transition"
                :canplay="exercise.resultCorrect != undefined"
                :autoplay="autoplay && exercise.resultCorrect != undefined"
                :class="
                    exercise.resultCorrect != undefined
                        ? ''
                        : 'blur select-none'
                "
                :word="exercise.word"
            />

            <WordMeaning :word="exercise.word" />
        </template>

        <template #answer>
            <div class="flex flex-col items-center">
                <div class="flex text-xl mb-8">
                    <span class="invisible">Hi</span>

                    <span>
                        {{ exercise.result }}
                    </span>

                    <span class="invisible">Hi</span>
                </div>

                <Transition
                    :enter-active-class="
                        playAnimation
                            ? 'animated animated-jack-in-the-box ad-500'
                            : ''
                    "
                    :leave-active-class="
                        playAnimation ? 'animated animated-fade-out ad-100' : ''
                    "
                    mode="out-in"
                >
                    <div
                        v-if="exercise.resultCorrect != undefined"
                        class="flex"
                    >
                        <i
                            v-if="exercise.resultCorrect === true"
                            class="i-bi-check text-5xl text-green-6"
                        ></i>

                        <i
                            v-if="exercise.resultCorrect === false"
                            class="i-bi-x text-5xl text-red-6"
                        ></i>
                    </div>

                    <div v-else class="flex items-center">
                        <i
                            v-show="exercise.resultCorrect != true"
                            class="i-bi-x text-5xl"
                            :class="
                                exercise.result == undefined
                                    ? 'text-red-2'
                                    : 'text-red-6'
                            "
                            @click="handleClickError"
                        ></i>

                        <div
                            class="ml-8 mr-8"
                            v-show="exercise.resultCorrect == undefined"
                        >
                            <Transition
                                enter-active-class="animated animated-duration-150 animated-zoom-in"
                                leave-active-class="animated animated-duration-150 animated-zoom-out"
                                mode="out-in"
                            >
                                <L2
                                    size="3rem"
                                    color="#4f46e5"
                                    border-width="0.2rem"
                                    v-if="asr.status.value == 'not-ready'"
                                />
                                <div
                                    v-else-if="asr.status.value == 'leisure'"
                                    class="flex justify-center items-center w-12 h-12 border-4 border-solid border-gray-300 rounded-full"
                                >
                                    <div
                                        @click="start"
                                        class="i-bi-record-fill text-5xl text-red-6"
                                    ></div>
                                </div>

                                <div
                                    v-else-if="asr.status.value == 'recording'"
                                    class="flex justify-center items-center w-12 h-12 border-4 border-solid border-gray-300 rounded-full"
                                >
                                    <i
                                        @click="stop"
                                        class="i-bi-stop-fill text-5xl text-red-6"
                                    ></i>
                                </div>

                                <L32
                                    v-else-if="asr.status.value == 'processing'"
                                    size="3rem"
                                    color="#4f46e5"
                                    border-width="0.2rem"
                                />
                            </Transition>
                        </div>

                        <i
                            v-show="exercise.resultCorrect != false"
                            class="i-bi-check text-5xl"
                            :class="
                                exercise.resultCorrect
                                    ? 'text-green-6'
                                    : 'text-green-2'
                            "
                        ></i>
                    </div>
                </Transition>
            </div>
        </template>
    </BaseExercise>
</template>

<script setup lang="ts">
    import { ChinesePronounceEnglishExercise } from "../../model"
    import { replaceNumbersWithWords, useTimekeeping } from "../../utils"
    import SimpleWord from "../word/SimpleWord.vue"
    import PhoneticSymbol from "../word/PhoneticSymbol.vue"
    import BaseExercise from "./BaseExercise.vue"
    import L2 from "../common/loading/L2.vue"
    import L32 from "../common/loading/L32.vue"
    import { useASR } from "../../utils"
    import WordMeaning from "../word/WordMeaning.vue"
    import { onMounted, onUnmounted, ref, toRef, watch } from "vue"

    const props = defineProps<{
        exercise: ChinesePronounceEnglishExercise
        actived: boolean
        autoplay?: boolean
    }>()

    const timekeeping = useTimekeeping()

    const asr = useASR()

    const playAnimation = ref(false)

    onMounted(() => {
        document.addEventListener("keyup", handleKeyup)
    })

    onUnmounted(() => {
        document.addEventListener("keyup", handleKeyup)
        if (asr.status.value == "recording") {
            asr.stop()
        }
    })

    watch(toRef(props.actived), (a) => {
        if (!a) {
            if (asr.status.value == "recording") {
                asr.stop()
            }
        }
    })

    function handleKeyup(e: KeyboardEvent) {
        if (!props.actived) {
            return
        }
        if (e.code == "Space") {
            if (asr.status.value == "leisure") {
                start()
            } else if (asr.status.value == "recording") {
                stop()
            }
        } else if (e.code == "ArrowLeft") {
            handleClickError()
        }
    }

    function start() {
        asr.start()
    }

    function stop() {
        asr.stop().then((str) => {
            if (!str) return
            props.exercise.timekeeping = Math.trunc(timekeeping.value / 3)
            str = replaceNumbersWithWords(str)
            props.exercise.result = str
            if (checkResult(str)) {
                playAnimation.value = true
                props.exercise.resultCorrect = true
            }
        })
    }

    function handleClickError() {
        if (props.exercise.result != undefined) {
            playAnimation.value = true
            props.exercise.resultCorrect = false
        }
    }

    function checkResult(r: string) {
        const arr = r.split(" ")
        for (let s of arr) {
            if (s.charCodeAt(s.length - 1) < 65) {
                s = s.slice(0, -1)
                s = s.toLowerCase()
            }
            const w = props.exercise.word.toLowerCase()
            if (s == w) {
                return true
            }
        }
        return false
    }
</script>
